package me.zhengjie.modules.docparse.parse;

import me.zhengjie.modules.docparse.util.StreamUtils;
import me.zhengjie.modules.docparse.domain.dto.FileDto;
import me.zhengjie.modules.docparse.domain.enums.TitleEnum;
import me.zhengjie.modules.docparse.domain.vo.StructableWordVo;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.StyleDescription;
import org.apache.poi.hwpf.model.StyleSheet;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;


@me.zhengjie.modules.docparse.annotation.Parser(fileType = {"doc", "docx"})
public class WordParser implements Parser<StructableWordVo> {

    /**
     * 输入流转换后的字节数组(用于流复用)
     */
    private byte[] bytes;


    @Override
    public StructableWordVo parse(FileDto fileDto) {
        bytes = StreamUtils.inputToByteArray(fileDto.getInputStream());

        StructableWordVo vo = new StructableWordVo();
        List<StructableWordVo.Head> heads = fileDto.getSuffx().equals("doc") ? getHwpfHead() : getXwpfHead();
        vo.setContent(parseToString(new ByteArrayInputStream(bytes)));
        return vo;
    }


    @Override
    public StructableWordVo parse(String path) throws IOException {
        StructableWordVo wordVo = new StructableWordVo();
        List<String> result = doc2String(path);
        wordVo.setContent(result.get(0));
        wordVo.setAbstractContent(result.get(1));
        wordVo.setIndexContent(result.get(2));
//        wordVo.setHeads(getHead(path));
        return wordVo;
    }


    public String getDocType(String docType,String buffer ,String regex){
        if(buffer.length() > 0){
            //使用回车换行符分割字符串
            String [] arry = buffer.split(regex);
            List<String> formatList = new ArrayList<String>();
            for (String string : arry) {
                formatList.add(string.trim());
            }
            String docTypeContent = "";//摘要
            int docTypeIndex = -1;
            for (String string : formatList) {
                String content = string.replace(" ", "");

                if(content.toUpperCase().endsWith(docType)){
                    docTypeIndex = formatList.indexOf(string);
                    //遇到中文摘要跳出
                    break;
                }
            }
            if(docTypeIndex>0){
                for (int i=docTypeIndex; i<formatList.size(); i++) {
                    if (formatList.get(i).equals("")){
                        //空余3行，可能摘要和摘要内容之间可能存在空行
                        if( i<docTypeIndex+3){
                            docTypeContent = docTypeContent + formatList.get(i).trim();
                        }else {
                            break;
                        }
                    }
                    docTypeContent = docTypeContent + formatList.get(i).trim()+"\n";;
                }
                return docTypeContent;
            }

        }
        return "";
    }

    public List<String> doc2String(String filePath){

        List<String> linList = new ArrayList<String>();
        String buffer = "";
        try {
            if (filePath.endsWith(".doc")) {
                InputStream is = new FileInputStream(new File(filePath));
                WordExtractor ex = new WordExtractor(is);
                buffer = ex.getText();
                linList.add(buffer);
                ex.close();
                linList.add( getDocType("摘要",buffer,"\\r\\n"));
                String indexContent = getDocType("目录",buffer,"\\r\\n");
                if(indexContent.equals("")){

                    for (StructableWordVo.Head head: getHead(filePath)) {
                        if(head.getTitle().replace(" ", "").equals("")){
                            continue;
                        }
                        indexContent = indexContent + head.getTitle()+"\n";
                    }
                }
                linList.add(indexContent);
            } else if (filePath.endsWith(".docx")) {
                OPCPackage opcPackage = POIXMLDocument.openPackage(filePath);
                XWPFWordExtractor extractor = new XWPFWordExtractor(opcPackage);
                buffer = extractor.getText();
                linList.add(buffer);
                extractor.close();
                linList.add( getDocType("摘要",buffer,"\\n"));
                linList.add( getDocType("目录",buffer,"\\n"));

            } else {
                return null;
            }

            return linList;
        } catch (Exception e) {
            System.out.print("error---->"+filePath);
            e.printStackTrace();
            return null;
        }
    }



    public List<StructableWordVo.Head> getHead(String path) {
        File file = new File(path);
        if (file.getAbsolutePath().toUpperCase().endsWith(".DOC")) {

            return getHwpfHead(path);
        }
        if (file.getAbsolutePath().toUpperCase().endsWith(".DOCX")) {

            return getXwpfHead(path);
        }

        return null;
    }

    private List<StructableWordVo.Head> getXwpfHead() {
        List<StructableWordVo.Head> heads = new ArrayList<>();
        XWPFDocument document = null;
        try (InputStream is = new ByteArrayInputStream(bytes)) {
            document = new XWPFDocument(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (int i = 0; i < paragraphs.size(); i++) {
            String style = paragraphs.get(i).getStyle();
            if (style != null) {
                //(n-1)一般代表几级标题
                if (isInteger(style)){
                    if (Integer.parseInt(style) < 7) {
                        StructableWordVo.Head head = new StructableWordVo.Head();
                        head.setTitle(paragraphs.get(i).getText());
                        head.setStyle(TitleEnum.findTitle(Integer.parseInt(style)));
                        heads.add(head);
                    }
                }

            }

        }
        return heads;
    }


    private List<StructableWordVo.Head> getXwpfHead(String path) {
        List<StructableWordVo.Head> heads = new ArrayList<>();
        File file = new File(path);
        XWPFDocument document = null;

        try {
            document = new XWPFDocument(new FileInputStream(file));
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (int i = 0; i < paragraphs.size(); i++) {
            String style = paragraphs.get(i).getStyle();
            if (style != null) {
                //(n-1)一般代表几级标题
                if (isInteger(style)){
                    if (Integer.parseInt(style) < 7) {
                        StructableWordVo.Head head = new StructableWordVo.Head();
                        head.setTitle(paragraphs.get(i).getText());
                        head.setStyle(TitleEnum.findTitle(Integer.parseInt(style)));
                        heads.add(head);
                    }
                }
            }
        }
        return heads;
    }


    public boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }
    private List<StructableWordVo.Head> getHwpfHead() {
        List<StructableWordVo.Head> heads = new ArrayList<>();

        HWPFDocument doc = null;
        try (InputStream is = new ByteArrayInputStream(bytes)) {
            doc = new HWPFDocument(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Range r = doc.getRange();
        for (int i = 0; i < r.numParagraphs(); i++) {
            Paragraph p = r.getParagraph(i);
            int numStyles = doc.getStyleSheet().numStyles();
            int styleIndex = p.getStyleIndex();
            if (numStyles > styleIndex) {
                StyleSheet style_sheet = doc.getStyleSheet();
                StyleDescription style = style_sheet.getStyleDescription(styleIndex);
                String styleName = style.getName();
                if (styleName != null && styleName.contains("标题")) {
                    StructableWordVo.Head head = new StructableWordVo.Head();
                    head.setTitle(p.text());
                    heads.add(head);
                }
            }
        }
        return heads;
    }



    private List<StructableWordVo.Head> getHwpfHead(String path) {
        List<StructableWordVo.Head> heads = new ArrayList<>();

        HWPFDocument doc = null;

        try {
            doc = new HWPFDocument(new FileInputStream(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Range r = doc.getRange();
        for (int i = 0; i < r.numParagraphs(); i++) {
            Paragraph p = r.getParagraph(i);
            int numStyles = doc.getStyleSheet().numStyles();
            int styleIndex = p.getStyleIndex();
            if (numStyles > styleIndex) {
                StyleSheet style_sheet = doc.getStyleSheet();
                StyleDescription style = style_sheet.getStyleDescription(styleIndex);
                String styleName = style.getName();
                if (styleName != null && styleName.contains("标题")) {
                    StructableWordVo.Head head = new StructableWordVo.Head();
                    head.setTitle(p.text());
                    heads.add(head);
                }
            }
        }
        return heads;
    }


    private List<String> doGetTitle2007(File file) {
        List<String> list = new ArrayList<>();
        InputStream is = null;
        XWPFDocument document = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            document = new XWPFDocument(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (int i = 0; i < paragraphs.size(); i++) {
            String style = paragraphs.get(i).getStyle();
            if (style != null) {
                //n代表几级标题
                if (Integer.parseInt(style) < 9) {
                    list.add(paragraphs.get(i).getText());
                }
            }

        }
        return list;
    }

    private List<String> doGetTitle2007(InputStream inputStream) {
        List<String> list = new ArrayList<>();
        XWPFDocument document = null;

        try (InputStream is = inputStream) {
            document = new XWPFDocument(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (int i = 0; i < paragraphs.size(); i++) {
            String style = paragraphs.get(i).getStyle();
            if (style != null) {
                //n代表几级标题
                if (Integer.parseInt(style) < 9) {
                    list.add(paragraphs.get(i).getText());
                }
            }

        }
        return list;
    }

    public static void main(String[] args) throws IOException {
        WordParser wd = new WordParser();
        StructableWordVo wordVo  = wd.parse("D:\\002图纸\\001\\毕业设计\\夜大\\新建文件夹 (2)\\2012毕业设计最终稿\\论文\\吸尘器说明书（终极版）（庞武明毕业设计）.doc");
        System.out.println(wordVo.getAbstractContent());
        System.out.println(wordVo.getIndexContent());
//        System.out.println(wordVo.getContent());
//        for (int i = 0; i < wordVo.getHeads().size(); i++) {
//            System.out.println(wordVo.getHeads().get(i).getTitle());
//        }
    }
}
